using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Voodoo.Sauce.Debugger.Widgets;

namespace Voodoo.Sauce.Debugger
{
	public static class WidgetUtility
	{
		private const string BANK_PATH = "VoodooDebuggerWidgetBank";

		private static DebuggerCanvas _debuggerCanvasPrefab;

		private static Dictionary<string, Widget> _bank;

		static WidgetUtility()
		{
			_bank = new Dictionary<string, Widget>();
			WidgetBank widgetBank = Resources.Load<WidgetBank>("VoodooDebuggerWidgetBank");
			_debuggerCanvasPrefab = widgetBank.debuggerPrefab;
			Widget[] widgets = widgetBank.widgets;
			foreach (Widget widget in widgets)
			{
				Type type = widget.GetType();
				if (type.FullName != null)
				{
					_bank.Add(type.FullName, widget);
				}
			}
		}

		public static T Get<T>(string key) where T : Widget
		{
			if (!_bank.ContainsKey(key))
			{
				throw new KeyNotFoundException("Widget was not found inside bank : '" + key + "'");
			}
			return (T)_bank[key];
		}

		public static Widget Get(string key)
		{
			return _bank[key];
		}

		public static DebuggerCanvas InstantiateDebugger()
		{
			return UnityEngine.Object.Instantiate(_debuggerCanvasPrefab);
		}

		public static T InstanceOf<T>(Transform parent = null) where T : Widget
		{
			return UnityEngine.Object.Instantiate(Get<T>(typeof(T).FullName), parent);
		}

		public static DebugMenuItemButton MenuItem(string title, Sprite image, Color imageColor, Action callback, BadgeCounter counter = null, Transform parent = null)
		{
			DebugMenuItemButton debugMenuItemButton = InstanceOf<DebugMenuItemButton>(parent);
			debugMenuItemButton.SetText(title);
			debugMenuItemButton.SetIcon(image, imageColor);
			debugMenuItemButton.SetCallback(callback);
			debugMenuItemButton.SetBadgeCounter(counter);
			return debugMenuItemButton;
		}

		public static DebugHideableSection Foldout(string title, Transform parent = null)
		{
			DebugHideableSection debugHideableSection = InstanceOf<DebugHideableSection>(parent);
			if (debugHideableSection == null)
			{
				return null;
			}
			debugHideableSection.GetComponentInChildren<Text>().text = title;
			return debugHideableSection;
		}

		public static DebugTextPair Label(Func<string> refreshFunc, Transform parent = null)
		{
			return CopyToClipboard(string.Empty, refreshFunc, null, isWarning: false, parent);
		}

		public static DebugTextPair Label(string text, Transform parent = null)
		{
			return CopyToClipboard(text, null, null, isWarning: false, parent);
		}

		public static DebugTextPair Label(string text, string value, Transform parent = null)
		{
			return CopyToClipboard(text, () => value, null, isWarning: false, parent);
		}

		public static DebugTextPair Label(string text, Func<string> refreshFunc, Transform parent = null)
		{
			return CopyToClipboard(text, refreshFunc, null, isWarning: false, parent);
		}

		public static DebugTextPair CopyToClipboard(string label, string value, Transform parent = null)
		{
			return CopyToClipboard(label, () => value, () => value, isWarning: false, parent);
		}

		public static DebugTextPair CopyToClipboard(string label, Func<string> refreshFunc, Transform parent = null)
		{
			return CopyToClipboard(label, refreshFunc, refreshFunc, isWarning: false, parent);
		}

		public static DebugTextPair CopyToClipboard(string label, string value, Func<string> valueToCopy, Transform parent = null)
		{
			return CopyToClipboard(label, () => value, valueToCopy, isWarning: false, parent);
		}

		public static DebugTextPair CopyToClipboard(string label, Func<string> refreshFunc, Func<string> valueToCopy, bool isWarning = false, Transform parent = null)
		{
			DebugTextPair debugTextPair = InstanceOf<DebugTextPair>(parent);
			debugTextPair.SetLabel(label);
			debugTextPair.SetValue(refreshFunc?.Invoke());
			debugTextPair.SetRefreshFunc(refreshFunc);
			if (isWarning)
			{
				debugTextPair.SetStyle(Color.red, FontStyle.Bold);
			}
			if (valueToCopy == null)
			{
				debugTextPair.ShowCopyButton(value: false);
			}
			else
			{
				debugTextPair.SetValueToCopy(valueToCopy?.Invoke());
				debugTextPair.SetRefreshToCopyFunc(valueToCopy);
			}
			return debugTextPair;
		}

		public static void CreateSpace(int height = 10, Transform parent = null)
		{
			CreateSeparator(height, displayLine: false, parent);
		}

		public static void CreateSeparator(int height = 10, Transform parent = null)
		{
			CreateSeparator(height, displayLine: true, parent);
		}

		public static void CreateSeparator(int height, bool displayLine, Transform parent = null)
		{
			DebugSeparator debugSeparator = InstanceOf<DebugSeparator>(parent);
			debugSeparator.SetSize(height);
			debugSeparator.DisplayLine(displayLine);
		}

		public static DebugButtonWithInputField Button(string title, Action callback, Transform parent = null)
		{
			DebugButtonWithInputField debugButtonWithInputField = InstanceOf<DebugButtonWithInputField>(parent);
			debugButtonWithInputField.SetTitle(title);
			debugButtonWithInputField.SetButtonCallback(callback);
			debugButtonWithInputField.SetInputField(active: false);
			if (callback == null)
			{
				debugButtonWithInputField.SetEnable(enable: false);
			}
			return debugButtonWithInputField;
		}

		public static DebugButtonWithInputField ButtonWithInput(string title, string placeholderText, Action<string> callback, Func<string> refreshFunc = null, Transform parent = null)
		{
			DebugButtonWithInputField debugButtonWithInputField = InstanceOf<DebugButtonWithInputField>(parent);
			debugButtonWithInputField.SetTitle(title);
			debugButtonWithInputField.SetButtonCallback(callback);
			debugButtonWithInputField.SetInputField(active: true, placeholderText);
			debugButtonWithInputField.SetRefreshFunc(refreshFunc);
			if (callback == null)
			{
				debugButtonWithInputField.SetEnable(enable: false);
			}
			return debugButtonWithInputField;
		}

		public static DebugButtonWithInputField InputField(string title, string placeholderText, Action<string> inputCallback, Func<string> refreshFunc = null, Transform parent = null)
		{
			DebugButtonWithInputField debugButtonWithInputField = InstanceOf<DebugButtonWithInputField>(parent);
			debugButtonWithInputField.SetTitle(title);
			debugButtonWithInputField.SetInputCallback(inputCallback);
			debugButtonWithInputField.SetInputField(active: true, placeholderText);
			debugButtonWithInputField.SetRefreshFunc(refreshFunc);
			return debugButtonWithInputField;
		}

		public static DebugToggleButton Toggle(string title, bool value, Action<bool> callback, Transform parent = null)
		{
			DebugToggleButton debugToggleButton = InstanceOf<DebugToggleButton>(parent);
			debugToggleButton.Initialize(title, value, callback);
			return debugToggleButton;
		}

		public static DebugRadioButton RadioButton(string label, Action<bool> callback, Transform parent)
		{
			DebugRadioButton debugRadioButton = InstanceOf<DebugRadioButton>(parent);
			debugRadioButton.SetLabel(label);
			debugRadioButton.SetCallback(callback);
			return debugRadioButton;
		}

		public static DebugRowLabel RowLabel(string rowName, string value, Transform parent = null)
		{
			return RowLabel(rowName, new string[1] { value }, parent);
		}

		public static DebugRowLabel RowLabel(string rowName, string[] values, Transform parent = null)
		{
			DebugRowLabel debugRowLabel = InstanceOf<DebugRowLabel>(parent);
			debugRowLabel.SetRowName(rowName);
			debugRowLabel.AddRows(values);
			return debugRowLabel;
		}

		public static DebugRadioGroup RadioGroup()
		{
			return new DebugRadioGroup();
		}

		public static DebugCheckboxButton CheckboxButton(string label, Action<bool> callback, Transform parent)
		{
			DebugCheckboxButton debugCheckboxButton = InstanceOf<DebugCheckboxButton>(parent);
			debugCheckboxButton.SetLabel(label);
			debugCheckboxButton.SetCallback(callback);
			return debugCheckboxButton;
		}
	}
}
